package com.broada.apm.util;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.broada.apm.indicator.api.ApmClientFactory;
import com.broada.apm.indicator.api.UserService;
import com.broada.apm.model.UserToken;
import com.broada.apm.utils.ExceptionUtils;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

/**
 * 
 * 
 * @author liss Create By 2014年11月25日 上午11:46:35
 */
public class CacheTokenManager {
	private static Logger LOG = LoggerFactory.getLogger(CacheTokenManager.class);
	public static UserService userService = ApmClientFactory.getApmClient().getUserService();
	private static CacheTokenManager MANAGER = new CacheTokenManager();

	RemovalListener<String, String> removalListener = new RemovalListener<String, String>() {
		public void onRemoval(RemovalNotification<String, String> removal) {
			try {
				userService.deleteUserToken(removal.getKey());
			} catch (Exception e) {
				ExceptionUtils.error(LOG, "用户token移除时发生错误", e);
			}
		}
	};
	private LoadingCache<String, String> cache = CacheBuilder.newBuilder().maximumSize(10000)
			.removalListener(removalListener).expireAfterAccess(5, TimeUnit.MINUTES).build(new CacheLoader<String, String>() {
				@Override
				public String load(String key) throws Exception {
					UserToken userToken = userService.getUserToken(key);
					return userToken == null ? "" : userToken.getValue();
				}
			});

	private CacheTokenManager() {
		loadCacheToken();
	}

	private void loadCacheToken() {
		try {
			/**
			 * 关闭tomcat情况下，需要处理数据库的token，这里重新加载。
			 */
			List<UserToken> userTokens = userService.getAllUserTokens();
			for (UserToken userToken : userTokens) {
				cache.put(userToken.getKey(), userToken.getValue());
			}
		} catch (Exception e) {
			ExceptionUtils.error(LOG, "用户token加载失败.", e);
		}
	}

	public static CacheTokenManager getInstance() {
		return MANAGER;
	}

	public void put(String key, String value) {
		UserToken userToken = new UserToken(key, value);
		if(userService.getUserToken(key) == null) 
			userService.addUserToken(userToken);
		cache.put(key, value);
	}

	public String get(String key) {
		return cache.getIfPresent(key);
	}

	/**
	 * 移除
	 * 
	 * @param key
	 */
	public void invalidate(String key) {
		cache.invalidate(key);
	}

}